home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / NN.C < prev    next >
C/C++ Source or Header  |  1989-12-31  |  11KB  |  544 lines

  1. /*
  2.  *    The User Interface main program
  3.  */
  4.  
  5. #include "config.h"
  6. #include "menu.h"
  7. #include "term.h"
  8. #include "keymap.h"
  9. #include "options.h"
  10.  
  11. static int
  12.     dont_read_init_file = 0,
  13.     prompt_for_group = 0;
  14.  
  15. static char
  16.     *match_subject = NULL;
  17.  
  18. export int
  19.     article_limit = -1,
  20.     also_read_articles = 0,
  21.     conf_auto_quit = 0,
  22.     do_kill_handling = 1,
  23.     group_name_args = 0,
  24.     merged_menu = 0,
  25.     silent = 0,
  26.     Debug = 0;
  27.  
  28. import int 
  29.     keep_rc_backup, no_update,                     /* rc.c */
  30.     preview_window, fmt_linenum, fmt_rptsubj,            /* menu.c */
  31.     show_article_date, first_page_lines,            /* more.c */
  32.     dont_split_digests, dont_sort_articles,            /* group.c */
  33.     dont_sort_folders,                        /* folder.c */
  34.     also_unsub_groups,                        /* sequence.c*/
  35.     show_current_time, conf_dont_sleep;                /* term.c */
  36.  
  37. Option_Description(nn_options) {
  38.     'a', Int_Option(article_limit),
  39.     'B', Bool_Option(keep_rc_backup),
  40.     'd', Bool_Option(dont_split_digests),
  41.     'f', Bool_Option(dont_sort_folders),
  42.     'g', Bool_Option(prompt_for_group),
  43.     'I', Bool_Option(dont_read_init_file),
  44.     'k', Bool_Option(do_kill_handling),
  45.     'l', Int_Option(first_page_lines),
  46.     'L', Int_Option_Optional(fmt_linenum, 3),
  47.     'm', Bool_Option(merged_menu),
  48.     'N', Bool_Option(no_update),
  49.     'q', Bool_Option(dont_sort_articles),
  50.     'Q', Bool_Option(silent),
  51.     's', String_Option(match_subject),
  52.     'S', Bool_Option(fmt_rptsubj),
  53.     'T', Bool_Option(show_current_time),
  54.     'w', Int_Option_Optional(preview_window, 5),
  55.     'W', Bool_Option(conf_dont_sleep),
  56.     'x', Int_Option_Optional(also_read_articles, -1),
  57.     'X', Bool_Option(also_unsub_groups),
  58.     'Z', Int_Option(Debug),
  59.     '\0',
  60. };
  61.  
  62.  
  63. static int
  64.     report_number_of_articles = 0,
  65.     report_group_names = 0;
  66. static char
  67.     *check_message_format = NULL;
  68.  
  69. Option_Description(check_options) {
  70.     'Q', Bool_Option(silent),
  71.     'r', Bool_Option(report_number_of_articles),
  72.     'f', String_Option(check_message_format),
  73.     't', Bool_Option(report_group_names),
  74.     '\0',
  75. };
  76.  
  77.  
  78. /* program name == argv[0] without path */
  79.  
  80. char *pname;
  81.  
  82.  
  83. main(argc, argv)
  84. int argc;
  85. char *argv[];
  86. {
  87.     extern long unread_articles;
  88.     extern char *program_name();
  89.     int emacs_slave_mode = 0, check_news = 0, enter_admin_mode = 0;
  90.     int who_am_i = 0;
  91.     
  92.     pname = program_name(argv);
  93.     if (strcmp(pname, "nnadmin") == 0) {
  94.     who_am_i = 2;
  95.     enter_admin_mode = 1;
  96.     } else
  97.     if (strcmp(pname, "nnemacs") == 0)
  98.     emacs_slave_mode = 1;
  99.     else
  100.     if (strcmp(pname, "nncheck") == 0) {
  101.     who_am_i = 3;
  102.     keep_rc_backup = 0;    
  103.     check_news = 1;
  104.     }
  105.     
  106.     if (!check_news && !emacs_slave_mode && (!enter_admin_mode || argc == 1))
  107.     if (!isatty(0)) {
  108.         fprintf(stderr, "Input is not a tty\n");
  109.         nn_exit(1);
  110.     }
  111.     
  112.     if (init_global(who_am_i) < 0) {
  113.     fprintf(stderr, "%s: nn has not been invoked to initialize user files\n", pname);
  114.     nn_exit(1);
  115.     }
  116.     
  117.     init_key_map();
  118.     init_execute();
  119.     init_macro();
  120.     open_master(OPEN_READ);
  121.     
  122. #ifdef NNTP
  123.     nntp_check();
  124. #endif
  125.     if (enter_admin_mode) {
  126.     visit_active_file();
  127.     if (argc == 1) {
  128.         init_term();
  129.         visit_init_file(0);
  130.     }
  131.     admin_mode(argv[1]);
  132.     nn_exit(0);
  133.     }
  134.  
  135.     if (check_news) {
  136.     group_name_args =
  137.         parse_options(argc, argv, (char *)NULL, check_options, " [group | [+]folder]...");
  138.     visit_init_file(1);
  139.     } else
  140.     if (!emacs_slave_mode) {
  141.     init_term();
  142.  
  143.     if (argc < 2 || strncmp(argv[1], "-I", 2))
  144.         visit_init_file(0);
  145.  
  146.     group_name_args =
  147.         parse_options(argc, argv, (char *)NULL,
  148.               nn_options, " [group | [+]folder]...");
  149.  
  150.     if (!silent)
  151.         print_version("Release %R.%V.%P #%U,  Kim F. Storm, 1989\n\n");
  152.     }
  153.  
  154.     if (also_read_articles) {
  155.     if (article_limit < 0) 
  156.         article_limit = also_read_articles;
  157.     do_kill_handling = 0;
  158.     no_update++;
  159.     }
  160.     
  161.     if (match_subject) {
  162.     if (*match_subject != '/') init_quick_match(match_subject);
  163.     no_update++;
  164.     do_kill_handling = 0;
  165.     }
  166.  
  167.     if (merged_menu) {
  168.     no_update++;
  169.     }
  170.     
  171.     if (!no_update && group_name_args > 0)
  172.     no_update = only_folder_args(argv + 1);
  173.     
  174.     visit_rc_file();
  175.  
  176.     if (group_name_args > 0)
  177.     named_group_sequence(argv + 1);
  178.     else
  179.     normal_group_sequence();
  180.  
  181.     count_unread_articles(report_group_names);
  182.  
  183.     if (emacs_slave_mode)
  184.     prt_unread("%U %G\n");
  185.     
  186.     if (check_news) {
  187.     if (check_message_format) {
  188.         if (unread_articles || !silent)
  189.         prt_unread(check_message_format);
  190.     } else    
  191.     if (report_number_of_articles) {
  192.         prt_unread("%U");
  193.         nn_exit(0);
  194.     } else
  195.     if (!silent) {
  196.         if (unread_articles || report_number_of_articles)
  197.         prt_unread("There %i %u in %g\n");
  198.         else 
  199.         prt_unread((char *)NULL);
  200.     }
  201.  
  202.     nn_exit( unread_articles ? 0 : 99 );
  203.     }
  204.     
  205.     if (unread_articles == 0 &&
  206.     group_name_args == 0 &&
  207.     !also_read_articles &&
  208.     !prompt_for_group) {
  209.     if (!silent) prt_unread((char *)NULL);
  210.     nn_exit(0);
  211.     }
  212.  
  213.     if (do_kill_handling)
  214.     do_kill_handling = init_kill();
  215.     
  216.     if (emacs_slave_mode) {
  217.     emacs_mode();
  218.     goto out;
  219.     }
  220.  
  221.     if (prompt_for_group) {
  222.     printf("\r\n\n"); 
  223.     raw();
  224.     current_group = NULL;
  225.     prompt_line = Lines - 3;
  226.     goto_group(K_GOTO_GROUP, (article_header *)NULL);
  227.     no_raw();
  228.     clrdisp();
  229.     goto out;
  230.     }
  231.     if (!no_update && article_limit == 0) {
  232.     char answer[50];
  233.  
  234.     prt_unread("\nCatch-up on %u ? (all) (i)nteractive ");
  235.     fl;
  236.     if (gets(answer)) {
  237.         if (strncmp(answer, "all", 3) == 0) {
  238.         printf("\nUPDATING rc FILE....");
  239.         fl;
  240.         read_news(-1);
  241.         printf("DONE\n");
  242.         goto out;
  243.         }
  244.         if (*answer == 'i') {
  245.         read_news(1);
  246.         goto out;
  247.         }
  248.     }
  249.     printf("\nNO UPDATE\n");
  250.     goto out;
  251.     }
  252.  
  253.     if (merged_menu) {
  254.     merge_and_read(match_subject, do_kill_handling);
  255.     clrdisp();
  256.     } else
  257.     if (read_news(0)) {
  258.     clrdisp();
  259.     } else {
  260.     gotoxy(0,Lines-1);
  261.     if (group_name_args == 0)
  262.         printf("No News\n");
  263.     else
  264.         printf("\r\n");
  265.     }
  266.     
  267. #ifdef STATISTICS    
  268.     log_usage();
  269. #endif    
  270.  
  271.     if (!also_read_articles && unread_articles > 0 && !silent && group_name_args == 0)
  272.     prt_unread("There %i still %u in %g\n\n\r");
  273.         
  274.  out:
  275.     
  276.     nn_exit(0);
  277.     /*NOTREACHED*/
  278. }
  279.  
  280. /* 
  281.  * nn_exit() --- called whenever a program exits.
  282.  */
  283.  
  284. nn_exit(n)
  285. {
  286.     static int loop = 0;
  287.     
  288.     if (loop) exit(n);
  289.     loop++;
  290.  
  291.     unset_raw();
  292.     visual_off();
  293.     
  294. #ifdef NNTP
  295.     nntp_cleanup();
  296. #endif /* NNTP */
  297.     close_master();
  298.     close_rc();
  299.     
  300.     exit(n);
  301. }
  302.  
  303. export group_header *jump_to_group = NULL;
  304.  
  305. static read_news(mode)
  306. {
  307.     register group_header *cur, *prev, *tmp, *after_loop;
  308.     int menu_cmd;
  309.     int must_clear = 0, did_jump = 0;
  310.     extern int menu();
  311.  
  312.     prev = group_sequence;
  313.     cur = group_sequence;
  314.     after_loop = NULL;
  315.     
  316.     while (cur != NULL || did_jump || conf_auto_quit) {
  317.     if (s_hangup) break;
  318.     
  319.     if (mode == 0 && cur == NULL) {
  320.         if (after_loop != NULL) {
  321.         cur = after_loop;
  322.         after_loop = NULL;
  323.         cur->last_article = cur->first_article;
  324.         continue;
  325.         }
  326.         if (did_jump) {
  327.         did_jump = 0;
  328.         cur = group_sequence;
  329.         continue;
  330.         }
  331.         if (!must_clear) return 0;
  332.         prompt("\1LAST GROUP READ.  QUIT NOW?\1");
  333.         switch (yes(1)) {
  334.          case 1: 
  335.         return 1;
  336.          case 0: 
  337.         cur = group_sequence;
  338.          default:
  339.         after_loop = prev;
  340.         continue;
  341.         }
  342.     }
  343.     
  344.     if (!also_read_articles)
  345.         if (cur->last_article >= cur->last_l_article) {
  346.         cur = cur->next_group;
  347.         continue;
  348.         }
  349.     
  350.     if (mode) {
  351.         if (mode > 0) {
  352.         char answer[50];
  353.         printf("Update %s (%ld)? ", 
  354.                cur->group_name,
  355.                (long)(cur->last_l_article - cur->last_article));
  356.         fl;
  357.         if (gets(answer) == NULL || s_keyboard) {
  358.             putchar(NL);
  359.             printf("Update rest? ");
  360.             fl;
  361.             if (gets(answer) == NULL || *answer != 'y')
  362.             return 0;
  363.             mode = -1;
  364.             *answer = 'y';
  365.         }
  366.         if (*answer == '?') {
  367.             printf("Enter (y)es to update current group\n");
  368.             continue; /* redo current group */
  369.         }
  370.         if (*answer != 'y') {
  371.             cur = cur->next_group;
  372.             continue;
  373.         }
  374.         }
  375.         update_rc(cur);
  376.         continue;
  377.     }
  378.     
  379.     free_memory();
  380.     
  381.     if (cur->group_flag & G_FOLDER) {
  382.         menu_cmd = folder_menu(cur->group_name);
  383.         if (menu_cmd == ME_NO_REDRAW) {
  384.         menu_cmd = ME_NO_ARTICLES;
  385.         cur->last_l_article = 0;
  386.         }
  387.     } else
  388.         menu_cmd = group_menu(cur, (article_number)(-1), 
  389.                   match_subject, do_kill_handling, menu);
  390.  
  391.     if (menu_cmd != ME_NO_ARTICLES) {
  392.         after_loop = NULL;
  393.         must_clear++;
  394.     }
  395.  
  396.     switch (menu_cmd) {
  397.         
  398.      case ME_PREV:
  399.         tmp = cur;
  400.         cur = prev;
  401.         prev = tmp;
  402.         cur->last_article = cur->first_article;
  403.         continue;
  404.         
  405.      case ME_READ:
  406.         cur->last_article = cur->last_l_article;
  407.         /* fall thru */
  408.         
  409.      case ME_NEXT:
  410.         prev = cur;
  411.         /* fall thru */
  412.         
  413.      case ME_NO_ARTICLES:
  414.         cur = cur->next_group;
  415.         continue;
  416.         
  417.      case ME_QUIT:
  418.         if (jump_to_group) {
  419.         prev = cur;
  420.         cur = jump_to_group;
  421.         jump_to_group = NULL;
  422.         did_jump = 1;
  423.         continue;
  424.         }
  425.         
  426.         return must_clear;
  427.     }    
  428.     }
  429.     return must_clear;
  430. }
  431.  
  432.  
  433.  
  434. export char *mail_box = NULL;
  435.  
  436. unread_mail(t)
  437. time_t t;
  438. {
  439.     struct stat st;
  440.     static time_t next = 0;
  441.     static int any = 0;
  442.     
  443.     if (next > t) return any;
  444.     
  445.     next = t + 60;
  446.     any = 0;
  447.     
  448.     if (mail_box == NULL ||
  449.     stat(mail_box, &st) != 0 ||
  450.     st.st_size == 0 || 
  451.     st.st_mtime < st.st_atime) return 0;
  452.     
  453.     any = 1;
  454.     
  455.     return 1;
  456. }
  457.  
  458. #ifdef STATISTICS
  459. static time_t usage_time = 0;
  460.  
  461. tick_usage(end_t, start_t)
  462. time_t *end_t, *start_t;
  463. {
  464.     time_t temp_t;
  465.     static time_t last_t = 0;
  466.     
  467.     if (end_t == NULL) end_t = &temp_t;
  468.     
  469.     time(end_t);
  470.     
  471.     if (start_t == 0) {
  472.     /* 
  473.      * We ignore delays > 2 minutes because the user has probably
  474.      * just left the terminal inside nn and done something else
  475.      */
  476.     if ((last_t + 120) > *end_t) 
  477.         usage_time += *end_t - last_t;
  478.     } else 
  479.     usage_time += (*end_t - *start_t)/60;
  480.     
  481.     last_t = *end_t;
  482. }
  483.  
  484. log_usage()
  485. {
  486.     usage_time /= 60;
  487.  
  488.     if (usage_time < STATISTICS) return; /* don't log short sessions */
  489.     
  490.     log_entry('U', "USAGE %d.%02d", usage_time/60, usage_time%60);
  491. }
  492. #endif
  493.  
  494. #ifdef MALLOC_TEST
  495. static int in_calloc = 0;
  496.  
  497. char *malloc(n)
  498. unsigned int n;
  499. {
  500.     char *p, *sbrk();
  501.     
  502.     if (p = sbrk(n + 3))
  503.     while ( ((int)p) & 3) p++;
  504.     
  505.     if (!in_calloc)
  506.     printf("MALLOC(%u) => %lx\n", n, (long)p);
  507.     
  508.     return p;
  509. }
  510.  
  511. char *calloc(n, s)
  512. unsigned n, s;
  513. {
  514.     char *p;
  515.     
  516.     in_calloc = 1;
  517.     p = malloc(n*s);
  518.     in_calloc = 0;
  519.     
  520.     printf("CALLOC(%u,%u) => %lx\n", n, s, (long)p);
  521.  
  522.     return p;
  523. }
  524.  
  525. free(p)
  526. char *p;
  527. {
  528.     printf("FREE(%lx)\n", p);
  529. }
  530.  
  531. char *realloc()
  532. {
  533.     printf("REALLOC\n");
  534. }
  535.  
  536. #endif /* MALLOC_TEST */
  537.  
  538. /* this will go into emacs_mode.c when it is completed someday */
  539.  
  540. emacs_mode()
  541. {
  542.     printf("EMACS MODE IS NOT SUPPORTED YET.\n");
  543. }
  544.